package com.iot.protocol;

import com.iot.protocol.client.UdpClient;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
public class UdpClientSimulator {
    private final String serverHost;
    private final int serverPort;
    private final int clientCount;
    private final int sendInterval;
    private final ExecutorService executorService;
    private final List<UdpClient> clients;
    private final AtomicInteger activeClients;
    private volatile boolean running;

    public UdpClientSimulator(String serverHost, int serverPort, int clientCount, int sendInterval) {
        this.serverHost = serverHost;
        this.serverPort = serverPort;
        this.clientCount = clientCount;
        this.sendInterval = sendInterval;
        this.executorService = Executors.newFixedThreadPool(clientCount);
        this.clients = new ArrayList<>(clientCount);
        this.activeClients = new AtomicInteger(0);
        this.running = true;
    }

    public void start() {
        log.info("开始模拟 {} 个UDP客户端连接到服务器 {}:{}", clientCount, serverHost, serverPort);
        CountDownLatch startLatch = new CountDownLatch(1);

        // 创建并启动所有客户端
        for (int i = 0; i < clientCount; i++) {
            final int clientId = i + 1;
            executorService.execute(() -> {
                try {
                    // 等待所有客户端准备就绪
                    startLatch.await();
                    
                    UdpClient client = new UdpClient(clientId, serverHost, serverPort, sendInterval);
                    clients.add(client);
                    activeClients.incrementAndGet();
                    log.info("UDP客户端-{} 已连接", clientId);

                    // 启动客户端
                    client.run();
                } catch (Exception e) {
                    log.error("UDP客户端-{} 发生错误: {}", clientId, e.getMessage(), e);
                } finally {
                    activeClients.decrementAndGet();
                }
            });
        }

        // 启动所有客户端
        startLatch.countDown();

        // 等待用户输入来控制模拟器
        try (Scanner scanner = new Scanner(System.in)) {
            System.out.println("UDP模拟器已启动，输入命令控制：");
            System.out.println("'status' - 查看当前状态");
            System.out.println("'interval <毫秒>' - 修改发送间隔");
            System.out.println("'exit' - 退出模拟器");

            while (running) {
                String command = scanner.nextLine().trim();
                if ("exit".equalsIgnoreCase(command)) {
                    break;
                } else if ("status".equalsIgnoreCase(command)) {
                    showStatus();
                } else if (command.startsWith("interval ")) {
                    try {
                        int newInterval = Integer.parseInt(command.substring("interval ".length()));
                        updateSendInterval(newInterval);
                    } catch (NumberFormatException e) {
                        System.out.println("无效的间隔时间，请输入数字（毫秒）");
                    }
                } else {
                    System.out.println("未知命令，可用命令：status, interval <毫秒>, exit");
                }
            }
        }

        // 关闭所有客户端
        shutdown();
    }

    private void showStatus() {
        System.out.printf("当前状态：\n" +
                "总客户端数：%d\n" +
                "活跃客户端数：%d\n" +
                "发送间隔：%d毫秒\n" +
                "服务器地址：%s:%d\n",
                clientCount, activeClients.get(), sendInterval, serverHost, serverPort);
    }

    private void updateSendInterval(int newInterval) {
        if (newInterval < 100) {
            System.out.println("发送间隔不能小于100毫秒");
            return;
        }
        log.info("更新所有客户端的发送间隔为 {} 毫秒", newInterval);
        for (UdpClient client : clients) {
            client.stop(); // 停止当前客户端
        }
        clients.clear();
        activeClients.set(0);
        
        // 使用新的间隔重新启动所有客户端
        for (int i = 0; i < clientCount; i++) {
            final int clientId = i + 1;
            executorService.execute(() -> {
                try {
                    UdpClient client = new UdpClient(clientId, serverHost, serverPort, newInterval);
                    clients.add(client);
                    activeClients.incrementAndGet();
                    log.info("UDP客户端-{} 已重新连接", clientId);
                    client.run();
                } catch (Exception e) {
                    log.error("UDP客户端-{} 重新连接时发生错误: {}", clientId, e.getMessage(), e);
                } finally {
                    activeClients.decrementAndGet();
                }
            });
        }
    }

    private void shutdown() {
        running = false;
        log.info("正在关闭UDP模拟器...");
        
        // 关闭所有客户端
        for (UdpClient client : clients) {
            try {
                client.stop();
            } catch (Exception e) {
                log.error("关闭客户端时发生错误: {}", e.getMessage(), e);
            }
        }
        
        // 关闭线程池
        executorService.shutdown();
        try {
            if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) {
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            executorService.shutdownNow();
            Thread.currentThread().interrupt();
        }
        
        log.info("UDP模拟器已关闭");
    }

    public static void main(String[] args) {
        String serverHost = "localhost";
        int serverPort = 8888;
        int clientCount = 5;    // 默认模拟5个客户端
        int sendInterval = 1000; // 默认发送间隔1秒

        if (args.length >= 1) {
            clientCount = Integer.parseInt(args[0]);
        }
        if (args.length >= 2) {
            serverHost = args[1];
        }
        if (args.length >= 3) {
            serverPort = Integer.parseInt(args[2]);
        }
        if (args.length >= 4) {
            sendInterval = Integer.parseInt(args[3]);
        }

        UdpClientSimulator simulator = new UdpClientSimulator(serverHost, serverPort, clientCount, sendInterval);
        simulator.start();
    }
} 